#include <iostream>
#include <sstream>
#include <string>
#include <vector>

#include <SDL/SDL.h>

#include "defines.h"

#include "estado_game.h"
#include "fonte.h"
#include "audio.h"
#include "controles.h"
#include "sprite.h"
#include "tetrimino.h"

using namespace std;

/******************************************************************************
    Construtor
    Seta o estado para futuras identificacoes
******************************************************************************/
Estado_Game::Estado_Game(int players) {
    tipo_estado = players;
    delay = 200;
    pause = false;
    end_game = 0;
}

/******************************************************************************
    Destrutor
    Deleta objetos instanciados
******************************************************************************/
Estado_Game::~Estado_Game(void) {
    for (int i = 0; i < tipo_estado; i++) {
        delete(m[i]);
    }
}

/******************************************************************************
    Carregar()
    Coloca na memoria todos elementos que serao utilizados por esta classe
******************************************************************************/
void Estado_Game::Carregar(void){
    std::vector<SDL_Rect> frames;
    
    tetriminos.push_front( new Tetrimino((rand() % 7) + 1, rand() % 4) );
    tetriminos.push_front( new Tetrimino((rand() % 7) + 1, rand() % 4) );
    
    Sprite::Carregar("bg",          "data/bg.bmp",          210, 500, frames);
#ifndef AUDIO_OFF
    Audio::Carregar("explosion","data/explosion.wav");
    Audio::Carregar("fix",      "data/fix.wav");
    Audio::Carregar("hit",      "data/hit.wav");
    Audio::Carregar("attack",   "data/attack.wav");
    Audio::Carregar("loss",     "data/loss.wav");
    Audio::Carregar("win",      "data/win.wav");
#endif

    //Inicializa matrizes de jogo
	for ( int i = 0; i < tipo_estado; i++) {
	   m[i] = new MatrizJogo(i, &tetriminos);
    }
  
    tetriminos.push_back( new Tetrimino((rand() % 7) + 1, rand() % 4) );
    tetriminos.push_back( new Tetrimino((rand() % 7) + 1, rand() % 4) );
    tetriminos.push_back( new Tetrimino((rand() % 7) + 1, rand() % 4) );
    tetriminos.push_back( new Tetrimino((rand() % 7) + 1, rand() % 4) );
}

/******************************************************************************
    Atualizar
    Recebe os inputs e atualiza as entidades. Eh o responsavel pela transicao
******************************************************************************/
int Estado_Game::Atualizar(Uint32 tempo) {
    //Update nos eventos dos controles
    Controles::Atualizar();

    //Delay para que a tecla nao seja "apertada" milhoes de vezes
    if (delay <= 0) {

        //ESC pressionado
        if ( Controles::Get(5, 0) == 1 ) {
            return ESTADO_SPLASH;
        }
        
        //ENTER pressionado
        if ( Controles::Get(5, 1) == 1 ) {
            delay = 100;
            pause = (pause ? false : true);
        }
    }
    //Se tiver com um delay, nao recebe nenhum input, soh aguarda
    else {
        delay -= tempo;
    }
    
    if (!pause) {
        //Atualiza a matriz do jogo
        int game_over_count = 0;
        for (int i = 0; i < tipo_estado; i++) {
            m[i]->Atualizar(tempo);
            if (m[i]->gameOver != 0 ) {
               game_over_count++;
            }
        }
        
        
        //Verifica se alguem venceu
        if ( game_over_count >= tipo_estado - 1 ) {
             for (int i = 0; i < tipo_estado; i++) {
                 if (m[i]->gameOver == 0 ) {
                     end_game = i+1;
                     break;
                 }
             }
        } else {
            if (tipo_estado != 1) {
                for (int i = 0; i < tipo_estado; i++) {
                    //Realiza ataque
                    if (m[i]->atack > 0) {
                       //Loop para nao atacar a si mesmo e nem a ninguem morto
                        while ( 1 ) {
                            m[i]->vitima = rand() % tipo_estado;
                            if ( m[i]->vitima == i ) {
                                 continue;
                            }
                            if ( m[m[i]->vitima]->gameOver != 0 ) {
                                 continue;
                            }
                            break;
                        }
    
                        m[ (m[i]->vitima) ]->dano += m[i]->atack;
                        m[i]->atack = 0;
                    }
                }
            }
        }
        
        //Remove tetriminos ja usados da lista, e adiciona mais um.
        if ( tetriminos.front()->count >= tipo_estado ) {
             tetriminos.pop_front();
             tetriminos.push_back( new Tetrimino((rand() % 7) + 1, rand() % 4) );
        }
    }

    return ESTADO_NO_CHANGE;
}

/******************************************************************************
    Desenhar
    Chama as entidades e as desenha na tela
******************************************************************************/
void Estado_Game::Desenhar(SDL_Surface *tela) {
    //Se nao tiver pause, nem end game, desenha o jogo
    if (pause) {
        //Desenha mensagem de pause.
        Fonte::Print(420, 250, "Jogo Pausado", 255, 0, 0, 1, 1, "vtks_128", tela);        
    }
    //verifica se foi fim do jogo
    else if (end_game != 0) {
        string ss;
        ss = "Player ";
        char p[2];
        itoa(end_game, p, 10);
        ss.append(p);
        Fonte::Print(420, 250, ss.c_str() , 255, 0, 0, 1, 1, "vtks_128", tela);
        Fonte::Print(420, 400, " Venceu!" , 255, 0, 0, 1, 1, "vtks_128", tela);
    } 
    //Senao... desenha normal
    else {
        SDL_Rect dst = {0,0,0,0};
        for (int i = 0; i < tipo_estado; i++) {
            m[i]->Draw();
        	SDL_BlitSurface( m[i]->jogo, NULL, tela, &dst );
        	dst.x += 210;
        }
    }
    
}
